from wormbane.Feature import Wall
from wormbane.Thing import Thing


class Tile(Thing):

    def __init__(self, pos, level):
        Thing.__init__(self)
        self.__pos = pos
        self.env = level
        self.room = None
        self.monster = None
        self.__items = []
        self.__feature = None
        self.feature = Wall()
        self.known = None
        self.lit = False

    @property
    def pos(self):
        return self.__pos

    def __get_feature(self):
        return self.__feature

    def __set_feature(self, feature):
        if self.__feature is not None:
            self.__feature.env = None
        self.__feature = feature
        if self.__feature is not None:
            self.__feature.env = self

    feature = property(__get_feature, __set_feature)

    @property
    def char(self):
        if self.monster:
            return self.monster.char
        elif self.top_item:
            return self.top_item.char
        elif self.feature:
            return self.feature.char
        else:
            return ' '

    @property
    def top_item(self):
        return self.__items[-1] if self.__items else None

    @property
    def items(self):
        return reversed(self.__items)

    def add_item(self, item):
        # Keep impassable items last in the list, i.e. on top of the stack.
        items = self.__items
        if not items or items[-1].passable or not item.passable:
            items.append(item)
        else:
            # The top item is impassable and we are inserting a passable item.
            # Search from the top of the stack for an insertion point.
            for i in reversed(xrange(len(items) - 1)):
                if items[i].passable:
                    items.insert(i + 1, item)
                    break
            else:
                items.insert(0, item)

    def remove_item(self, item):
        self.__items.remove(item)

    @property
    def neighbors(self):
        tiles = self.level.tiles
        x, y = self.pos
        for dx, dy in ((-1, 1), (0, 1), (1, 1), (-1, 0), (1, 0), (-1, -1),
                       (0, -1), (1, -1)):
            try:
                yield tiles[x + dx][y + dy]
            except IndexError:
                pass

    @property
    def tile(self):
        return self

    @property
    def level(self):
        return self.env

    def search(self):
        return self.feature.search() if self.feature else None
